from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBasic, OAuth2PasswordBearer
import jwt
from jwt import PyJWTError
from datetime import datetime, timedelta
from oauthlib.oauth2 import BackendApplicationClient
from requests_oauthlib import OAuth2Session

app = FastAPI()

# Настройки для базовой HTTP-аутентификации
security_basic = HTTPBasic()

# Настройки для JWT
SECRET_KEY = "mysecretkey"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

# Пример защищенного маршрута с базовой HTTP-аутентификацией
@app.get("/protected_basic")
def protected_basic_route(credentials: HTTPBasic.credentials = Depends(security_basic)):
    if credentials.username != "user" or credentials.password != "password":
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Неверные имя пользователя или пароль",
            headers={"WWW-Authenticate": "Basic"},
        )
    return {"message": "Доступ разрешен (Базовая HTTP-аутентификация)"}

# Генерация JWT токена
def create_access_token(data: dict, expires_delta: timedelta):
    to_encode = data.copy()
    expire = datetime.utcnow() + expires_delta
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

# Пример защищенного маршрута с использованием JWT
@app.get("/protected_jwt")
def protected_jwt_route(token: str = Depends(oauth2_scheme)):
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Не авторизован",
                headers={"WWW-Authenticate": "Bearer"},
            )
    except PyJWTError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Не авторизован",
            headers={"WWW-Authenticate": "Bearer"},
        )
    return {"message": "Доступ разрешен (JWT)"}

# Генерация токена JWT для тестирования
@app.get("/token")
def login_for_access_token():
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": "user"}, expires_delta=access_token_expires
    )
    return {"access_token": access_token, "token_type": "bearer"}

# Настройки для OAuth2
CLIENT_ID = "your-client-id"
CLIENT_SECRET = "your-client-secret"
TOKEN_URL = "https://example.com/token"

# Пример защищенного маршрута с использованием OAuth2
@app.get("/protected_oauth2")
def protected_oauth2_route(token: str = Depends(oauth2_scheme)):
    # В реальном приложении нужно реализовать логику проверки токена OAuth2
    return {"message": "Доступ разрешен (OAuth2)"}

# Пример получения токена OAuth2
@app.get("/oauth2_token")
def login_for_oauth2_token():
    client = BackendApplicationClient(client_id=CLIENT_ID)
    oauth = OAuth2Session(client=client)
    token = oauth.fetch_token(token_url=TOKEN_URL, client_id=CLIENT_ID, client_secret=CLIENT_SECRET)
    return token
